﻿// -----------------------------------------------------------------------
// <copyright file="StudentDetailsService.cs" company="AGR">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace AGR.Services.Student.Contract
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using AGR.Model;
    using AGR.Data.Repository;
    using AGR.Data.Repository.Contract;
    using AGR.Services.Exceptions;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class StudentDetailsService : IStudentDetailsService
    {
        private ContextHelper _contextHelper;

        private IRepository<Student> _studentRepository;
        private IRepository<Course> _courseRepository;
        private IRepository<FactStudentCourse> _factStudentCourseRepository;
        private IRepository<SubjectProgress> _subjectProgressRepository;

        public StudentDetailsService()
        {
            _contextHelper = ContextHelper.GetInstance();

            _studentRepository = new StudentRepository(_contextHelper);
            _courseRepository = new CourseRepository(_contextHelper);
            _factStudentCourseRepository = new FactStudentCourseRepository(_contextHelper);
            _subjectProgressRepository = new SubjectProgressRepository(_contextHelper);
        }

        public Student GetStudent(string studentCode)
        {
            if (string.IsNullOrEmpty(studentCode))
                throw new ArgumentNullException();

            Student student = _studentRepository.FindSingleBy(x => x.StudentCode == studentCode);

            if (student == null)
                throw new StudentNotFoundException();

            return student;
        }

        public string GetFullName(string studentCode)
        {
            if (string.IsNullOrEmpty(studentCode))
                throw new ArgumentNullException();

            Student student = _studentRepository.FindSingleBy(x => x.StudentCode == studentCode);

            if (student == null)
                throw new StudentNotFoundException();

            return student.LastName + ", " + student.FirstName;
        }

        public DateTime GetDateRegistered(string studentCode)
        {
            if (string.IsNullOrEmpty(studentCode))
                throw new ArgumentNullException();

            DateTime? date = (from x in _factStudentCourseRepository.FindBy(x => x.StudentCode == studentCode)
                              select x.DateRegistered).First();

            if (date == null)
                throw new NoRegisteredCoursesFoundException();

            return date.Value;
        }

        public int GetYearRegistered(string studentCode)
        {
            if (string.IsNullOrEmpty(studentCode))
                throw new ArgumentNullException();

            DateTime year = GetDateRegistered(studentCode);

            if (year == null)
                throw new NoRegisteredCoursesFoundException();

            return year.Year;
        }

        public int GetYearGraduated(string studentCode)
        {
            if (string.IsNullOrEmpty(studentCode))
                throw new ArgumentNullException();

            throw new NotImplementedException();
        }

        public IList<Course> GetCourses(string studentCode)
        {
            if (string.IsNullOrEmpty(studentCode))
                throw new ArgumentNullException();

            var courseCodes = (from x in _factStudentCourseRepository.FindBy(x => x.StudentCode == studentCode)
                               select x.CourseCode);

            if (courseCodes == null)
                throw new NoRegisteredCoursesFoundException();

            IList<Course> courses = new List<Course>();

            foreach (string courseCode in courseCodes)
            {
                courses.Add(_courseRepository.FindSingleBy(x => x.CourseCode == courseCode));
            }

            if (courses.Count == 0)
                throw new NoRegisteredCoursesFoundException();

            return courses;
        }

        public IList<Subject> GetSubjects(string studentCode)
        {
            //dbo.Students stud
            //INNER JOIN dbo.FactStudentCourses fsc (NOLOCK) ON fsc.StudentCode = stud.StudentCode
            //INNER JOIN [StudentSubjectProgresses] fcst (NOLOCK) ON fcst.StudentCode = fsc.StudentCode 
            //INNER JOIN dbo.Subjects sub (NOLOCK) ON sub.SubjectCode = fcst.SubjectCode

            throw new NotImplementedException();
        }

        public IList<Subject> GetIncompletedSubjects(string studentCode)
        {
            throw new NotImplementedException();
        }

        public IList<Subject> GetCompletedSubjects(string studentCode)
        {
            throw new NotImplementedException();
        }

        public IList<CourseProgress> GetCourseProgresses(string studentCode)
        {
            throw new NotImplementedException();
        }

        public CourseProgress GetCourseProgress(string studentCode, string courseCode)
        {
            throw new NotImplementedException();
        }

        public IList<AttendanceCertificate> GetAttendanceCertificates(string studentCode)
        {
            throw new NotImplementedException();
        }

        public IList<Placement> GetPlacementHistory(string studentCode)
        {
            throw new NotImplementedException();
        }

        #region Private Methods

        private static void ActionResultError(ActionResult actionResult, Exception ex)
        {
            actionResult.Exception = ex;
            actionResult.IsSystemFailure = true;
            actionResult.Success = false;
        }

        #endregion

        #region Dispose

        private bool disposed = false;

        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    _contextHelper.Dispose();
                }
            }
            this.disposed = true;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        #endregion
    }
}
